#include "Shell.h"

	Shell::Shell(LibraryFunctions* libFunc) :
		shouldExit(false), libFunctions(libFunc) {
		currentlyRunningProcess = NULL;
		prcoessesThreadsMap.clear();
	}

	Shell::~Shell() {}

	void Shell::run() {
		string keyBoardInput;
		string delimChar = " \t\n";

		while (!shouldExit) {
			vector<string> stringVector;
			cout << ">";
			getline (cin, keyBoardInput);
			parseString(keyBoardInput, delimChar, stringVector);
			if (stringVector.size() > 0) {
				int commandResult = processCommand(stringVector);
				if (commandResult != 1) {
					cout << commandResult << endl;
				}
			}
		}
	}

	int Shell::parseString(string sStringToParse, string delimChar,
			vector<string>& rReturnStringArray) {

	 const char* str = sStringToParse.c_str();
	 const char* seps = delimChar.c_str();
	 char* token = NULL;
	 int i = 0;

	   /* Establish string and get the first token: */
	   token =  strtok( (char*)str, seps );

	   while( token != NULL ) {

		  /* While there are tokens in "string" */

		 rReturnStringArray.push_back( string(token));

		 i++;

		  /* Get next token: */
		  token = strtok( NULL, seps );
	   }

	 return i;
	}

	int Shell::processCommand (vector<string>& userInput) {
		if (userInput.size() != 0) {
			string command = userInput.front();
			if (command.compare("crprc") == 0 && userInput.size() == 3) {
				return crprc(atoi(userInput.at(1).c_str()),atoi(userInput.at(2).c_str()));
			} else if (command.compare("swprc") == 0 && userInput.size() == 2) {
				return swprc(atoi(userInput.at(1).c_str()));
			} else if (command.compare("batch") == 0 && userInput.size() == 2) {
				return batch(userInput.at(1).c_str());
			} else if (command.compare("exit") == 0 && userInput.size() == 1) {
				/*
				vector<string>* commandVector = new vector<string> (userInput);
				map<int,Process*>::iterator iter = prcoessesThreadsMap.begin();
				while (iter != prcoessesThreadsMap.end()) {
					iter->second->addCommand(commandVector);
				}
				*/
				shouldExit = true;
				return 0;
			} else {
				if (currentlyRunningProcess == NULL) {
					cerr << "No process running!" << endl;
					return -1;
				} else {
					vector<string>* commandVector = new vector<string> (userInput);
					currentlyRunningProcess->addCommand(commandVector);
					return 1;
				}
			}
		}
		return -1;
	}

	int Shell::swprc (int newProcessNum){
		int retValue = libFunctions->swprc(newProcessNum);
		if (retValue != -1) {
				map<int,Process*>::iterator iter = prcoessesThreadsMap.find(newProcessNum);
				currentlyRunningProcess = iter->second;
		}
		return retValue;
	}

	int Shell::crprc (int id, int parent){
		int retValue = libFunctions->crprc(id, parent);
		if (retValue != -1) {
			Process* newProcess = new Process (id, libFunctions);
			prcoessesThreadsMap.insert(pair<int,Process*> (id, newProcess));
			newProcess->start();
		}
		return retValue;
	}

	int Shell::batch (const char* fileName){
		fstream batchFile;
		string line;
		string delimChar = " ";
		batchFile.open(fileName, ios::in);
		if (batchFile.is_open()) {
			vector<string> parsedLine;
			while (!batchFile.eof()) {
				parsedLine.clear();
				getline(batchFile,line);
				parseString(line,delimChar,parsedLine);
				processCommand (parsedLine);
			}
			batchFile.close();
			return 0;
		} else {
			cerr << "Can't open batch file " << fileName << endl;
			return -1;
		}
	}

